#include "broker.h"
#include "auth.hpp"

#define TIMER_ID                   10000
#define TIMER_ID_CON               TIMER_ID + 1
#define TIMER_ID_HEART             TIMER_ID + 2
#define SCHANENEL_BIND_ADDR_MAXLEN 250

CBrokerImpl::CBrokerImpl(void)
{
}
CBrokerImpl::~CBrokerImpl(void)
{
    logi("CBrokerImpl::~CBrokerImpl");
}
HRESULT CBrokerImpl::Listen(LPCSTR addr, size_t len, int maxconn)
{
    m_MaxConn = maxconn;

    HRESULT hr = S_OK;

    hr = Init();
    rc_error(hr == S_OK, E_FAIL);

    rc_error(addr != NULL, E_FAIL);
    rc_error(len != 0, E_FAIL);

    CharArrayPtr item;
    item.dispose();
    item = ALLOC_NEW char[SCHANENEL_BIND_ADDR_MAXLEN + 1]();
    rc_error(item.m_p != NULL, E_FAIL);
    s_strcpy(item, SCHANENEL_BIND_ADDR_MAXLEN, addr);

    char* port = NULL;
    char* ip = NULL;

    ip = s_strtok(item, ":", &port);
    rc_error(ip != NULL, E_FAIL);
    rc_error(port != NULL, E_FAIL);

    hr = m_pIListen->Listen(ip, atoi(port));
    rc_error(hr == S_OK, E_FAIL);

    hr = m_pIListen->Accept(LISTEN_OPEN);
    rc_error(hr == S_OK, E_FAIL);

    return hr;
}
HRESULT CBrokerImpl::Dispatch(unsigned int sec)
{
    HRESULT hr = S_OK;

    loge("CBrokerImpl::Dispatch");

    m_sem.WaitTime(sec);

    return hr;
}

HRESULT CBrokerImpl::Close()
{
    HRESULT hr = S_OK;

    hr = UnInit();
    rc_error(hr == S_OK, E_FAIL);

    hr = this->CloseChannel();
    rc_error(hr == S_OK, E_FAIL);

    return hr;
}
HRESULT CBrokerImpl::IsListen()
{
    return IsListenChannel();
}
HRESULT CBrokerImpl::Accept(_sock_t s, SOCKADDR_PTR sa, socklen_t sl, crterr error_code)
{
    HRESULT hr = S_OK;

    return hr;
}

HRESULT CBrokerImpl::OnComplete(IBase* pOperation, crtid cid, crterr err)
{
    if (err == S_SUCCESS) {
        switch (cid) {
        case BUS_OP_RECV_SEQ:
            OnRecvSeqed(pOperation);
            break;
        case BUS_OP_SEND_SEQ_ACK:
            OnSendSeqAcked(pOperation);
            break;
        case BUS_OP_RECV_ACK:
            OnRecvAcked(pOperation);
            break;
        case BUS_OP_SEND:
            break;
        case BUS_OP_RECV:
            break;
        default:
            loge("CBrokerImpl::OnComplete");
            break;
        }
    } else {
        loge("CBrokerImpl::OnComplete::error %u", err);
    }
    return S_OK;
}
HRESULT CBrokerImpl::OnTimer(crtid cid, crterr err)
{
    // logi("id==>%u", uId);
    return S_OK;
}
HRESULT CBrokerImpl::CreateSChannel(IBase* pRot)
{
    HRESULT hr = S_OK;
    rc_error(pRot != NULL, E_FAIL);

    hr = pRot->QueryInterface(IID_IRot, (void**)&m_pRot);
    rc_error(hr == S_OK, E_FAIL);

    hr = m_pRot->GetObject(CLSID_CAsynFrame, IID_IAsynFrame, (IBase**)&m_pIAsynFrame);
    rc_error(hr == S_OK, E_FAIL);

    hr = m_pIAsynFrame->CreateIo(io_tcplisten_ssl_socket, (IBase**)&m_pIListen);
    rc_error(hr == S_OK, E_FAIL);

    return S_OK;
}
HRESULT CBrokerImpl::OpenCChannel()
{
    HRESULT hr = S_OK;

    hr = m_pIListen->CreateSock();
    rc_error(hr == S_OK, E_FAIL);

    hr = m_pIListen->OpenIo();
    rc_error(hr == S_OK, E_FAIL);

    hr = m_pIListen->BindIo();
    rc_error(hr == S_OK, E_FAIL);

    return hr;
}
HRESULT CBrokerImpl::CloseChannel()
{
    HRESULT hr = S_OK;

    hr = m_pIListen->CloseIo(CLOSE_BOTH_IO);
    rc_error(hr == S_OK, E_FAIL);

    hr = m_pIListen->CloseSock();
    rc_error(hr == S_OK, E_FAIL);

    hr = m_pIListen->UnBindAccpet();
    rc_error(hr == S_OK, E_FAIL);

    m_pIListen.dispose();

    m_pIAsynFrame.dispose();

    m_pRot.dispose();

    return S_OK;
}

HRESULT CBrokerImpl::OnAccepted(IBase* pBase, _sock_t s)
{
    HRESULT hr = S_OK;

    return S_OK;
}
HRESULT CBrokerImpl::OnRecvSeqed(IBase* pIBase)
{
    HRESULT hr = S_OK;

    unsigned int s = 0;
    unsigned int a = 0;

    // BusProtocol_Get_Seq_Ack(ptr, &s, &a);
    //  logi("s_recv==>seq:%u,ack:%u", s, a);

    // BusProtocol_2nd(ptr, BUS_ACK_VALUE, s);

    // Send(pIScoket, pIOperation, BUS_PROTOCOL_HEAD_LEN, BUS_OP_SEND_SEQ_ACK);

    return hr;
}
HRESULT CBrokerImpl::OnSendSeqAcked(IBase* pIBase)
{
    HRESULT hr = S_OK;

    // hr = Recv(pIScoket, pIOperation, BUS_PROTOCOL_HEAD_LEN, BUS_OP_RECV_ACK);
    // rc_error(hr == S_OK, E_FAIL);

    return hr;
}
HRESULT CBrokerImpl::OnRecvAcked(IBase* pIBase)
{
    HRESULT hr = S_OK;

    buf_len TransferedBytes = 0;
    buf_ptr ptr = NULL;
    unsigned int s = 0;
    unsigned int a = 0;

    hr = BusProtocol_Get_Seq_Ack(ptr, &s, &a);
    rc_error(hr == S_OK, E_FAIL);

    // logi("s_recv==>seq:%u,ack:%u", s, a);
    // logi("s_recv==>accept_bus_client");

    return hr;
}

HRESULT CBrokerImpl::Init()
{
    SYNC_OBJ(&m_lock);

    HRESULT hr = S_OK;

    hr = this->UnBindEvent();
    rc_error(hr == S_OK, E_FAIL);

    _lComPtr<IBase> pBase;

    hr = this->QueryInterface(IID_IBase, (void**)&pBase);
    rc_error(hr == S_OK, E_FAIL);

    hr = this->BindEvent(pBase);
    rc_error(hr == S_OK, E_FAIL);

    return hr;
}
HRESULT CBrokerImpl::UnInit()
{
    HRESULT hr = S_OK;

    m_AcceptQueue.auto_clear();

    return hr;
}
HRESULT CBrokerImpl::PushQueue(IBase* pBase)
{
    return S_OK;
}
